/**
 * Copyright(c) 2013-2014 by Puhuifinance Inc.
 * All Rights Reserved
 */
package com.puhui.chome.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author CHOME
 * @date 2014年9月17日
 */
public class DateUtil {

    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);
    public static final String SHORT_DATE_PATTERN = "yyyyMMdd";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DATETIME_PATTERN_YM = "yyyy-MM";

    private DateUtil() {
    }

    /**
     * 日期转换成字符串
     * 
     * @param date
     *            日期
     * @return String
     */
    public static String dateConvertString(Date date) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        return format.format(date);
    }

    /**
     * 用pattern指定的格式格式date
     * 
     * @param date
     *            日期
     * @param pattern
     *            日期格式
     * @return String
     */
    public static String dateConvertString(Date date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }

    /**
     * @Description: 日期转换成标准日期格式
     * @param date
     * @return
     * @date 2014年9月17日
     */
    public static Date dateConvertDate(Date date) {
        String dateString = dateConvertString(date);
        return stringConvertDate(dateString);
    }

    /**
     * 转换日期格式
     * 
     * @param dateStr
     *            日期格式
     * @return Date
     */
    public static Date stringConvertDate(String dateStr) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            logger.error("转化日期格式异常" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 转化字符串日期为Date
     * 
     * @param dateStr
     *            日期字符串
     * @param pattern
     *            日期格式
     * @return Date
     */
    public static Date stringConvertDate(String dateStr, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            logger.error("转化字符串日期为Date异常" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 时间字符串转化成日期
     * 
     * @param dateStr
     *            日期字符串
     * @return Date
     */
    public static Date stringConvertDateTime(String dateStr) {
        SimpleDateFormat format = new SimpleDateFormat(DATETIME_PATTERN);
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            logger.error("时间字符串转化成日期异常" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 转化date日期为字符串
     * 
     * @param date
     *            日期
     * @return String
     */
    public static String dateConvertStringTime(Date date) {
        SimpleDateFormat format = new SimpleDateFormat(DATETIME_PATTERN);
        try {
            return format.format(date);
        } catch (Exception e) {
            logger.error("转化date日期为字符串异常" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 日期月份加法
     * 
     * @author dingxingang
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    /**
     * 获取日期所在全年周数（中国）
     * 
     * @return
     */
    public static int getWeekNumber(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int weekNum = c.get(Calendar.WEEK_OF_YEAR);
        // 如果日期为周日，周数-1
        int hour = c.get(Calendar.DAY_OF_WEEK);
        if (hour == 1) {
            weekNum = weekNum - 1;
        }
        return weekNum;
    }

    /**
     * 获取日期所在全年天数（中国）
     * 
     * @return
     */
    public static int getDayNumber(Date date) {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        c.setTime(date);
        return c.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * 根据全年指定天数获取日期（中国）
     * 
     * @author puhui
     * @param dayNum
     *            全年指定天数
     * @return
     */
    public static Date getDayFromDayNumber(int dayNum) {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        c.set(Calendar.DAY_OF_YEAR, dayNum);
        return c.getTime();
    }

    /**
     * 获取日期所在周日日期
     * 
     * @author dingxingang
     * @param date
     * @return
     */
    public static Date getWeekMondaySaturday(Date date) {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        c.setFirstDayOfWeek(Calendar.MONDAY); // 以周1为首日
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return c.getTime();
    }

    /**
     * 日期天数加法
     * 
     * @author dingxingang
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    /**
     * 日期分钟加法
     * 
     * @author dingxingang
     * @param date
     * @param amount
     * @return
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    /**
     * 获取日期所在周一日期
     * 
     * @param date
     * @return
     */
    public static Date getWeekMonday(Date date) {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        c.setFirstDayOfWeek(Calendar.MONDAY); // 以周1为首日
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return c.getTime();
    }

    /**
     * 字符串的日期格式的计算
     */
    public static int daysBetween(String smdate, String bdate) {
        if (StringUtil.isEmpty(smdate) || StringUtil.isEmpty(bdate)) {
            return 0;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(DateUtil.stringConvertDate(smdate, DATE_PATTERN));
        long time1 = cal.getTimeInMillis();
        cal.setTime(DateUtil.stringConvertDate(bdate, DATE_PATTERN));
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 日期加法
     * 
     * @param date
     * @param calendarField
     *            参数
     * @param amount
     * @return
     */
    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            return null;
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, amount);
            return c.getTime();
        }
    }

    /**
     * 比对两日期大小
     * 
     * @param DATE1
     * @param DATE2
     * @return DATE1>=DATE2 : true (DATE1 在 DATE2之后)
     */
    public static boolean compare(Date date1, Date date2) {
        return date1.getTime() >= date2.getTime();
    }

    /**
     * 字符串转秒 格式 **小时**分**秒
     * 
     * @author xupeixi
     * @return
     */
    public static Double strConvertSecond(String str) {
        int hoursInx = str.indexOf("小");
        int hours1Inx = str.indexOf("时");
        int minuteInx = str.indexOf("分");
        int secondInx = str.indexOf("秒");
        double hours = 0; // 时
        double minute = 0;// 分
        double second = 0; // 秒
        if (hoursInx > 0) {
            hours = Double.parseDouble(str.substring(0, hoursInx)) * 3600;
        }
        if (minuteInx > 0 && hours1Inx <= 0) {
            minute = Double.parseDouble(str.substring(0, minuteInx)) * 60;
        }
        if (minuteInx > 0 && hours1Inx > 0) {
            minute = Double.parseDouble(str.substring(hours1Inx + 1, minuteInx)) * 60;
        }
        if (secondInx > 0 && minuteInx <= 0) {
            second = Double.parseDouble(str.substring(0, secondInx));
        }
        if (secondInx > 0 && minuteInx > 0) {
            second = Double.parseDouble(str.substring(minuteInx + 1, secondInx));
        }
        second = hours + minute + second;
        return second;
    }

    /**
     * 时间转换 秒转字符 格式 为 **小时**分**秒
     * 
     * @author xupeixi
     * @param second
     * @return
     */
    public static String secondConvertStr(Double secondCount) {
        int hours = 0;// 时
        int minute; // 分
        int second = 0; // 秒
        if ((int) (secondCount % 60) == 0) {
            minute = (int) (secondCount / 60);
        } else {
            minute = (int) (secondCount / 60);
            second = (int) (secondCount % 60);
        }
        if (minute > 60) {
            if (minute % 60 == 0) {
                hours = minute / 60;
                minute = 0;
            } else {
                hours = minute / 60;
                minute = minute % 60;
            }
        }
        String callTime = "";
        if (hours >= 0) {
            callTime = hours + "时";
        }
        if (minute >= 0) {
            callTime = callTime + minute + "分";
        }

        callTime = callTime + second + "秒";
        return callTime;

    }

    /**
     * 返回日期- 日
     * 
     * @author xupeixi
     * @param date
     * @return
     */
    public static int getDayByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 返回日期- 月
     * 
     * @author dingxingang
     * @param date
     * @return
     */
    public static int getMonthByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 返回日期- 年
     * 
     * @author dingxingang
     * @param date
     * @return
     */
    public static int getYearByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 返回日期- 分
     * 
     * @author dingxingang
     * @param date
     * @return
     */
    public static int getMinuteByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MINUTE);
    }

    /**
     * 获取传入时间所在月的最后一天 - 日
     * 
     * @param args
     */
    public static int getMonthLastDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取传入时间所在月的最后一天 - 日期
     * 
     * @param args
     */
    public static Date getMonthLastDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 两个日期之间相差几个月;如果多一天或几天则月+1
     * 
     * @param args
     */
    public static int differenceMonth(Date firstDate, Date nowDate) {
        Calendar fcal = Calendar.getInstance();
        fcal.setTime(firstDate);
        int fyear = fcal.get(Calendar.YEAR);
        int fmonth = fcal.get(Calendar.MONTH) + 1;
        int fday = fcal.get(Calendar.DAY_OF_MONTH);

        Calendar ncal = Calendar.getInstance();
        ncal.setTime(nowDate);
        int nyear = ncal.get(Calendar.YEAR);
        int nmonth = ncal.get(Calendar.MONTH) + 1;
        int nday = ncal.get(Calendar.DAY_OF_MONTH);
        int diffMonth = (nyear - fyear) * 12 + (nmonth - fmonth);
        if (nday - fday > 0) {
            diffMonth++;
        }
        return diffMonth;
    }

    /**
     * 将特殊格式（HH:mm）（23:59）字符串转成当日日期
     * 
     * @author liufei
     * @return
     */
    public static Date strToDate(String strDate) {
        Calendar cal = Calendar.getInstance();
        String[] strD = strDate.split(":");
        cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(strD[0]));
        cal.set(Calendar.MINUTE, Integer.parseInt(strD[1]));
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当月第一天
     * 
     * @return
     */
    public static String getMonthFirstDay() {
        SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN);
        Calendar calendar = Calendar.getInstance();
        Date theDate = calendar.getTime();

        GregorianCalendar gcLast = (GregorianCalendar) Calendar.getInstance();
        gcLast.setTime(theDate);
        gcLast.set(Calendar.DAY_OF_MONTH, 1);
        String dayFirst = df.format(gcLast.getTime());
        StringBuilder str = new StringBuilder().append(dayFirst).append(" 00:00:00");
        return str.toString();
    }

    /**
     * 日期转换中文字符 YYYY年MM月DD日
     * 
     * @author xupeixi
     * @param date
     * @return
     */
    public static String dateConvertVoiceString(Date date) {
        if (null == date) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        return sdf.format(date);
    }

    /**
     * 计算两个日期之间相差的天数
     * 
     * @param smDate
     *            较小的时间
     * @param bigDate
     *            较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smDate, Date bigDate) {
        Date smdate = dateConvertDate(smDate);
        Date bdate = dateConvertDate(bigDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 判断两个时间相差多少秒
     * 
     * @author sunyongcan
     * @param startDate
     * @param endDate
     * @return
     */
    public static Long differenceSecond(Date startDate, Date endDate) {
        if (startDate == null || endDate == null)
            return null;
        return (endDate.getTime() - startDate.getTime()) / 1000;
    }

    /**
     * 判断是否是凡普金科账户（2016-11-01之后）
     * 
     * @author lihao
     * @return true 是
     */
    public static boolean isFinupThird(Date date) {
        return compare(dateConvertDate(date), stringConvertDate("2016-11-01"));
    }

    /**
     * 组装某天精确时间
     * 
     * @author dingxingang
     * @param date
     *            日期
     * @param hhmmss
     *            时分秒，满足格式HH:mm:ss
     * @return
     */
    public static Date assembleAccurateTime(Date date, String hhmmss) {
        String ymd = DateUtil.dateConvertString(date);
        String time = ymd + " " + hhmmss;
        return DateUtil.stringConvertDate(time, "yyyy-MM-dd HH:mm:ss");
    }

}
